import React, { memo, useEffect, useState, useCallback } from "react";
import { connect, useDispatch } from "react-redux";
import { Tree, Menu, Dropdown, Modal, Input, message, Popconfirm } from "antd";

import { WarpDiv } from "./style";
import {
  addFileOrFolder,
  addOpenFile,
  updateActiveFileId,
  updateFileOrFolderName,
  removeFileOrFolder,
  removeOpenFile,
  updateClip,
  pasteFileOrFolder,
  updateCopyId,
} from "../../redux/actions/files";
import { convertStoreToTreeData, getExtFromFile } from "../../utils/fileUtils";

const { DirectoryTree } = Tree;
const allowFielType = ["js", "ts", "txt", "json"];

const LeftNav = memo(function Index(props) {
  const [treeData, setTreeData] = useState();
  const dispatch = useDispatch();
  const [menu, setMenu] = useState();
  const [renameOrNewmodal, setRenameOrNewmodal] = useState(false);
  const [modalData, setModalData] = useState({});
  const [rightClickId, setRightClickId] = useState("");

  useEffect(() => {
    //files变化，列表重新运算，更新数据
    setTreeData(convertStoreToTreeData(props.files));
  }, [props.files]);

  useEffect(() => {
    //将文件和数据同步保存到本地
    localStorage.setItem("state", JSON.stringify(props.files));
  }, [props.files]);

  //选择
  const onSelect = useCallback(
    (_, info) => {
      const { isLeaf, title, key } = info.node;
      if (isLeaf) {
        //代表点击了文件，根据文件名截取文件类型
        const ext = getExtFromFile(title);
        //只有js\ts\json\txt可以浏览
        if (allowFielType.includes(ext)) {
          //让这个文件打开
          if (!props.files.openedFilesIdArr.includes(key)) {
            dispatch(addOpenFile(key));
          }
          //选中这个文件
          dispatch(updateActiveFileId(key));
        } else {
          message.info("仅支持js、ts、txt、json文件打开", 1);
        }
      } else {
        //点击文件夹，不用管，默认就好
      }
    },
    [dispatch, props.files]
  );

  //重命名
  const handleRename = useCallback(
    (key, title, isLeaf) => {
      console.log("重命名");
      //弹出重新命名modal
      setRightClickId(key);
      setModalData({
        type: isLeaf ? "renamefile" : "renamefolder",
        name: title,
      });
      setRenameOrNewmodal(true);
    },
    [setRightClickId, setModalData, setRenameOrNewmodal]
  );

  //复制
  const handleCopy = useCallback(
    (key) => {
      dispatch(updateCopyId(key));
    },
    [dispatch]
  );

  //粘贴
  const handlePaste = useCallback(
    (key) => {
      dispatch(pasteFileOrFolder(key));
    },
    [dispatch]
  );

  //剪切
  const handleClip = useCallback(
    (key) => {
      dispatch(updateClip(key));
    },
    [dispatch]
  );

  //删除
  const handleDelete = useCallback(
    (key) => {
      dispatch(removeFileOrFolder(key));
      dispatch(removeOpenFile(key));
    },
    [dispatch]
  );

  //新建文件
  const handleNewFile = useCallback(
    (key) => {
      setRightClickId(key);
      setModalData({
        type: "addfile",
        name: "",
      });
      setRenameOrNewmodal(true);
    },
    [setRightClickId, setModalData, setRenameOrNewmodal]
  );

  //新建文件夹
  const handleNewFolder = useCallback(
    (key) => {
      setRightClickId(key);
      setModalData({
        type: "addfolder",
        name: "",
      });
      setRenameOrNewmodal(true);
    },
    [setRightClickId, setModalData, setRenameOrNewmodal]
  );

  const { copyId, clipFileId } = props.files;
  //菜单上右键
  const handleRightClick = useCallback(
    ({ _, node }) => {
      const { key, title, isLeaf } = node;
      if (isLeaf) {
        //文件节点，拷贝、删除、剪切、重命名
        setMenu(
          <Menu>
            <Menu.Item key="1" onClick={() => handleCopy(key, title, isLeaf)}>
              复制
            </Menu.Item>
            <Menu.Item key="3" onClick={() => handleClip(key, title, isLeaf)}>
              剪切
            </Menu.Item>
            <Popconfirm
              title="确定删除？"
              onConfirm={() => handleDelete(key, title, isLeaf)}
              okText="确定"
              cancelText="取消"
            >
              <Menu.Item key="4">删除</Menu.Item>
            </Popconfirm>

            <Menu.Item key="5" onClick={() => handleRename(key, title, isLeaf)}>
              重命名
            </Menu.Item>
          </Menu>
        );
      } else {
        //文件夹节点
        if (key === "0" || key === 0) {
          //根节点，只能重命名
          setMenu(
            <Menu>
              <Menu.Item
                key="14"
                onClick={() => handleNewFile(key, title, isLeaf)}
              >
                新建文件
              </Menu.Item>
              <Menu.Item
                key="15"
                onClick={() => handleNewFolder(key, title, isLeaf)}
              >
                新建文件夹
              </Menu.Item>
              <Menu.Item
                key="6"
                onClick={() => handleRename(key, title, isLeaf)}
              >
                重命名
              </Menu.Item>
              {(copyId || clipFileId) && (
                <Menu.Item
                  key="6.6"
                  onClick={() => handlePaste(key, title, isLeaf)}
                >
                  粘贴
                </Menu.Item>
              )}
            </Menu>
          );
        } else {
          //普通文件夹节点，拷贝、删除、剪切、重命名、粘贴
          setMenu(
            <Menu>
              <Menu.Item
                key="7"
                onClick={() => handleNewFile(key, title, isLeaf)}
              >
                新建文件
              </Menu.Item>
              <Menu.Item
                key="8"
                onClick={() => handleNewFolder(key, title, isLeaf)}
              >
                新建文件夹
              </Menu.Item>
              <Popconfirm
                title="确定删除？"
                onConfirm={() => handleDelete(key, title, isLeaf)}
                okText="确定"
                cancelText="取消"
              >
                <Menu.Item key="9">删除</Menu.Item>
              </Popconfirm>
              <Menu.Item
                key="10"
                onClick={() => handleCopy(key, title, isLeaf)}
              >
                复制
              </Menu.Item>
              {(copyId || clipFileId) && (
                <Menu.Item
                  key="11"
                  onClick={() => handlePaste(key, title, isLeaf)}
                >
                  粘贴
                </Menu.Item>
              )}
              <Menu.Item
                key="12"
                onClick={() => handleClip(key, title, isLeaf)}
              >
                剪切
              </Menu.Item>
              <Menu.Item
                key="13"
                onClick={() => handleRename(key, title, isLeaf)}
              >
                重命名
              </Menu.Item>
            </Menu>
          );
        }
      }
    },
    [
      copyId,
      clipFileId,
      handleRename,
      handleClip,
      handlePaste,
      handleCopy,
      handleDelete,
      handleNewFolder,
      handleNewFile,
    ]
  );

  //确定
  const handleOk = useCallback(() => {
    //修改文件或者文件夹名称
    const { name, type } = modalData;
    const typeStr = type?.indexOf("add") >= 0 ? "新增" : "修改";
    const typeStr2 = type?.indexOf("folder") >= 0 ? "文件夹" : "文件";

    if (typeStr2 === "文件夹" && name.includes(".")) {
      message.error("文件夹名称不得包含点号");
      return;
    }
    if (typeStr2 === "文件" && !name.includes(".")) {
      message.error("文件名称请包含后缀名");
      return;
    }
    //提交action，修改名称
    if (typeStr === "修改") {
      //修改文件或者文件夹名称
      console.log(type);
      dispatch(updateFileOrFolderName(rightClickId, type, name));
    } else {
      //新增文件或者文件夹
      dispatch(
        addFileOrFolder(
          name,
          rightClickId === "0" ? 0 : rightClickId,
          props.files,
          typeStr2 === "文件",
          false,
          ""
        )
      );
    }
    //关闭页面
    setRenameOrNewmodal(false);
  }, [setRenameOrNewmodal, dispatch, rightClickId, props.files, modalData]);

  //取消
  const handleCancel = useCallback(() => {
    setRenameOrNewmodal(false);
    setModalData({});
  }, [setRenameOrNewmodal, setModalData]);

  const { name, type } = modalData;
  const typeStr = type?.indexOf("add") >= 0 ? "新增" : "修改";
  const typeStr2 = type?.indexOf("folder") >= 0 ? "文件夹" : "文件";

  return (
    <WarpDiv>
      {type && modalData && (
        <Modal
          destroyOnClose
          title={`${typeStr}${typeStr2}名称`}
          visible={renameOrNewmodal}
          onOk={handleOk}
          onCancel={handleCancel}
          okText="确定"
          cancelText="取消"
        >
          <Input
            placeholder={`请输入${typeStr}后的${typeStr2}名称`}
            onChange={(e) => {
              setModalData({ ...modalData, name: e.target.value });
            }}
            value={name}
          />
        </Modal>
      )}
      <Dropdown overlay={menu} trigger={["contextMenu"]}>
        <div className="dropdown">
          <div>
            {/* defaultExpandAll只会生效1次，即便treeData没有值，因此要有值才显示这个控件 */}
            {treeData && (
              <DirectoryTree
                onSelect={onSelect}
                defaultExpandAll={true}
                treeData={treeData}
                onRightClick={handleRightClick}
              />
            )}
          </div>
        </div>
      </Dropdown>
    </WarpDiv>
  );
});

export default connect((state) => ({ files: state.files }))(LeftNav);
